/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


// sv_commands.cpp -- operator console commands


#include "sv_local.h"


/*
 ==================
 SV_GetClientByNum

 Returns the client with id number from Cmd_Argv(1)
 ==================
*/
static client_t *SV_GetClientByNum (void){

	client_t	*client;
	const char	*string;
	int			num;
	int			i;

	string = Cmd_Argv(1);

	// Check for a valid slot number
	for (i = 0; string[i]; i++){
		if (!Str_CharIsDigit(string[i])){
			Com_Printf("Bad slot number: %s\n", string);
			return NULL;
		}
	}

	num = Str_ToInteger(string);
	if (num < 0 || num >= sv_maxClients->integerValue){
		Com_Printf("Bad slot number: %i\n", num);
		return NULL;
	}

	client = &svs.clients[num];
	if (client->state == CS_FREE){
		Com_Printf("Client with id number %i is not on the server\n", num);
		return NULL;
	}

	return client;
}

/*
 ==================
 SV_GetClientByName

 Returns the client with name from Cmd_Argv(1)
 ==================
*/
static client_t *SV_GetClientByName (void){

	client_t	*client;
	const char	*string;
	char		name[MAX_NAME_LENGTH];
	int			i;

	string = Cmd_Argv(1);

	// Check for a name match
	for (i = 0, client = svs.clients; i < sv_maxClients->integerValue; i++, client++){
		if (client->state == CS_FREE)
			continue;

		if (!Str_ICompare(client->name, string))
			return client;

		// Try without color sequences
		Str_Copy(name, client->name, sizeof(name));
		Str_RemoveColors(name);

		if (!Str_ICompare(name, string))
			return client;
	}

	Com_Printf("Client with name '%s' is not on the server\n", string);

	return NULL;
}

/*
 ==================
 SV_Map_f
 ==================
*/
void SV_Map_f (void){

	char	name[MAX_OSPATH];

	if (Cmd_Argc() != 2){
		Com_Printf("Usage: map <mapName>\n");
		return;
	}

	// Make sure the file exists
	Str_Copy(name, Cmd_Argv(1), sizeof(name));
	Str_DefaultFilePath(name, sizeof(name), "maps");
	Str_DefaultFileExtension(name, sizeof(name), ".bsp");

	if (FS_ReadFile(name, NULL) == -1){
		Com_Printf("Map %s not found\n", name);
		return;
	}

	// Spawn the server
	Str_StripFileExtension(name);

	SV_SpawnServer(name);
}

/*
 ==================
 SV_DevMap_f
 ==================
*/
void SV_DevMap_f (void){

	char	name[MAX_OSPATH];

	if (Cmd_Argc() != 2){
		Com_Printf("Usage: devMap <mapName>\n");
		return;
	}

	// Make sure the file exists
	Str_Copy(name, Cmd_Argv(1), sizeof(name));
	Str_DefaultFilePath(name, sizeof(name), "maps");
	Str_DefaultFileExtension(name, sizeof(name), ".bsp");

	if (FS_ReadFile(name, NULL) == -1){
		Com_Printf("Map %s not found\n", name);
		return;
	}

	// Spawn the server
	Str_StripFileExtension(name);

	SV_SpawnServer(name);
}

/*
 ==================
 SV_NextMap_f
 ==================
*/
void SV_NextMap_f (void){

	char	command[MAX_STRING_LENGTH];

	if (!svs.initialized){
		Com_Printf("Server is not running\n");
		return;
	}

	if (!sv_nextMap->value[0]){
		Com_Printf("No next map available\n");
		return;
	}

	Str_SPrintf(command, sizeof(command), "map %s\n", sv_nextMap->value);

	Cmd_AppendText(command);

	// Clear it out
	CVar_SetString(sv_nextMap, "");
}

/*
 ==================
 SV_KillServer_f
 ==================
*/
void SV_KillServer_f (void){

	if (!svs.initialized){
		Com_Printf("Server is not running\n");
		return;
	}

	// Kill the server, but also drop the client connection
	SV_Shutdown("Server was killed");
	CL_Drop("Server was killed");
}


/*
 ==================
 SV_ServerStatus_f
 ==================
*/
void SV_ServerStatus_f (void){

	client_t	*client;
	int			i;

	if (!svs.initialized){
		Com_Printf("Server is not running\n");
		return;
	}

	Com_Printf("\n");
	Com_Printf("Map: %s\n", sv_map->value);
	Com_Printf("\n");

	Com_Printf("num address               cport lastmsg rate  ping name\n");
	Com_Printf("--- --------------------- ----- ------- ----- ---- ----------------\n");

	for (i = 0, client = svs.clients; i < sv_maxClients->integerValue; i++, client++){
		if (client->state == CS_FREE)
			continue;

		Com_Printf("%3i ", i);

		Com_Printf("%-21s ", NET_NetAdrToString(client->peer));

		Com_Printf("%5i ", client->peer->address.port);

		switch (client->state){
		case CS_ZOMBIE:
			Com_Printf("ZMBI ");
			break;
		case CS_CONNECTED:
			Com_Printf("CNCT ");
			break;
		case CS_PRIMED:
			Com_Printf("PRMD ");
			break;
		default:
			break;
		}

		Com_Printf("%s\n", client->name);
	}

	Com_Printf("\n");
}

/*
 ==================
 SV_ServerInfo_f
 ==================
*/
void SV_ServerInfo_f (void){

	const char	*infoString;
	char		*ch;

	infoString = CVar_ServerInfoString();

	Com_Printf("Server info settings:\n");
	Com_Printf("---------------------\n");

	while (1){
		ch = Str_FindChar(infoString, '\\');
		if (!ch)
			break;

		*ch++ = 0;

		// Print the name/value pair
		Cmd_TokenizeString(infoString);

		Com_Printf("%-20s %s\n", Cmd_Argv(0), Cmd_Args(1, -1, false));

		// Advance
		infoString = (const char *)ch;
	}
}

/*
 ==================
 SV_DumpUserInfo_f
 ==================
*/
void SV_DumpUserInfo_f (void){

	client_t	*client;
	const char	*infoString;
	char		*ch;

	if (!svs.initialized){
		Com_Printf("Server is not running\n");
		return;
	}

	if (Cmd_Argc() != 2){
		Com_Printf("Usage: dumpUserInfo <number>\n");
		return;
	}

	client = SV_GetClientByNum();
	if (!client)
		return;

	infoString = client->userInfo;

	Com_Printf("User info settings:\n");
	Com_Printf("-------------------\n");

	while (1){
		ch = Str_FindChar(infoString, '\\');
		if (!ch)
			break;

		*ch++ = 0;

		// Print the name/value pair
		Cmd_TokenizeString(infoString);

		Com_Printf("%-20s %s\n", Cmd_Argv(0), Cmd_Args(1, -1, false));

		// Advance
		infoString = (const char *)ch;

		*--ch = '\\';
	}
}

/*
 ==================
 SV_KickClient_f
 ==================
*/
void SV_KickClient_f (void){

	client_t	*client;

	if (!svs.initialized){
		Com_Printf("Server is not running\n");
		return;
	}

	if (Cmd_Argc() != 2){
		Com_Printf("Usage: kickClient <number>\n");
		return;
	}

	client = SV_GetClientByNum();
	if (!client)
		return;

	SV_DropClient(client, "Kicked from the server");

}

/*
 ==================
 SV_KickPlayer_f
 ==================
*/
void SV_KickPlayer_f (void){

	client_t	*client;

	if (!svs.initialized){
		Com_Printf("Server is not running\n");
		return;
	}

	if (Cmd_Argc() != 2){
		Com_Printf("Usage: kickPlayer <name>\n");
		return;
	}

	client = SV_GetClientByName();
	if (!client)
		return;

	SV_DropClient(client, "Kicked from the server");

}

/*
 ==================
 SV_KickAll_f
 ==================
*/
void SV_KickAll_f (void){

	client_t	*client;
	int			i;

	if (!svs.initialized){
		Com_Printf("Server is not running\n");
		return;
	}

	for (i = 0, client = svs.clients; i < sv_maxClients->integerValue; i++, client++){
		if (client->state == CS_FREE)
			continue;

		SV_DropClient(client, "Kicked from the server");

	}
}
